#!/usr/bin/env python
# -*- coding: utf-8 -*-


import wx
import wx.aui

# region 常量字典和字典构建函数
ADD_LIST = 'add_list'
DEL_LIST = 'del_list'
CHG_LIST = 'chg_list'
CFL_LIST = 'cfl_list'
UNV_LIST = 'unv_list'

TITLE_KEY_DIC = {
    ADD_LIST: u'追加列表',
    DEL_LIST: u'删除列表',
    CHG_LIST: u'变更列表',
    CFL_LIST: u'冲突列表',
    UNV_LIST: u'版本外列表'
}

KEY_TITLE_DIC = {
    u'追加列表': ADD_LIST,
    u'删除列表': DEL_LIST,
    u'变更列表': CHG_LIST,
    u'冲突列表': CFL_LIST,
    u'版本外列表': UNV_LIST
}


def build_file_list(add_list, del_list, chg_list, cfl_list, unv_list):
    return {
        ADD_LIST: add_list,
        DEL_LIST: del_list,
        CHG_LIST: chg_list,
        CFL_LIST: cfl_list,
        UNV_LIST: unv_list
    }
# endregion


# region 事件定义
class WxChangeFileSelectionEvent(wx.PyCommandEvent):

    def __init__(self, evt_type, id):
        wx.PyCommandEvent.__init__(self, evt_type, id)

CHANGE_FILE_SELECTION_EVENT_TYPE = wx.NewEventType()
EVT_CHANGE_FILE_SELECTION = wx.PyEventBinder(CHANGE_FILE_SELECTION_EVENT_TYPE, 1)
# endregion


# region 提交对话框
class CommitPanel(wx.Panel):
    def __init__(self, *args, **kwargs):
        wx.Panel.__init__(self, *args, **kwargs)

        # main sizer
        sizer = wx.BoxSizer(wx.VERTICAL)

        # radio sizer
        radio_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.radio_type = radio_type = \
            wx.RadioBox(self, id=wx.ID_ANY, label=u'注释类型', choices=[u'摘要', u'明细'])
        radio_sizer.Add(radio_type, 0, wx.EXPAND)
        sizer.Add(radio_sizer, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 15)

        # message box
        message_box = wx.StaticBox(self, id=wx.ID_ANY, label=u'注释')
        message_sizer = wx.StaticBoxSizer(message_box, wx.HORIZONTAL)
        self.message = message = wx.TextCtrl(self, id=wx.ID_ANY, style=wx.TE_MULTILINE)
        sizer.Add(message_sizer, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 15)
        message_sizer.Add(message, 1, wx.EXPAND)

        # file list tree
        tree_box = wx.StaticBox(self, id=wx.ID_ANY, label=u'提交文件列表')
        tree_sizer = wx.StaticBoxSizer(tree_box, wx.HORIZONTAL)
        self.file_list_tree = file_list_tree = wx.TreeCtrl(self, id=wx.ID_ANY)
        tree_sizer.Add(file_list_tree, 1, wx.EXPAND)
        sizer.Add(tree_sizer, 1, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, 15)

        self.SetSizer(sizer)

        # connections
        self.Bind(wx.EVT_RADIOBOX, self.on_message_type_changed, radio_type)

        # region member variable
        self.files = []
        # endregion member variable

    def on_message_type_changed(self, event):
        radio_type = self.radio_type
        message = self.message
        message.Clear()
        # detail selected
        if radio_type.GetSelection() == 1:
            a = '\n\n'.join(self.files)
            message.AppendText(a)

    def set_file_list(self, file_list_dic):
        self.add_file_list(ADD_LIST, file_list_dic)
        self.add_file_list(DEL_LIST, file_list_dic)
        self.add_file_list(CHG_LIST, file_list_dic)
        self.add_file_list(CFL_LIST, file_list_dic)
        self.add_file_list(UNV_LIST, file_list_dic)

    def add_file_list(self, key, file_list_dic):

        flt = self.file_list_tree
        root = flt.GetRootItem()
        if not root:
            root = flt.AddRoot('文件列表')

        add_list = file_list_dic.get(TITLE_KEY_DIC[key])
        if add_list and len(add_list) > 0:
            add_node = flt.AppendItem(root, TITLE_KEY_DIC[key])
            for fl_name in add_list:
                self.files.append(fl_name)
                flt.AppendItem(add_node, fl_name)


class CommitDialog(wx.Dialog):
    def __init__(self, *args, **kwargs):
        wx.Dialog.__init__(self, *args, **kwargs)
        self.panel = panel = CommitPanel(self, id=wx.ID_ANY)

        sizer = wx.BoxSizer(wx.VERTICAL)
        # button: OK cancel
        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.ok_btn = ok = wx.Button(self, id=wx.ID_ANY, label='OK')
        self.cnl_btn = cnl = wx.Button(self, id=wx.ID_ANY, label='CANCEL')

        button_sizer.Add(ok, 0, wx.EXPAND)
        button_sizer.Add(cnl, 0, wx.EXPAND)
        sizer.Add(panel, 1, wx.EXPAND)
        sizer.Add(button_sizer, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, 15)

        self.SetSizer(sizer)

        # connections
        self.Bind(wx.EVT_BUTTON, self.on_ok_clicked, ok)
        self.Bind(wx.EVT_BUTTON, self.on_cnl_clicked, cnl)

    def on_ok_clicked(self, event):
        print 666

    def on_cnl_clicked(self, event):
        self.EndModal(wx.ID_CANCEL)

    def set_file_list(self, file_list_dic):
        self.panel.set_file_list(file_list_dic)

# endregion 提交对话框


# region 文件面板主panel
class FileListPanel(wx.Panel):

    def __init__(self, parent, *args, ** kwargs):
        wx.Panel.__init__(self, parent, *args, ** kwargs)

        # 放置list的sizer和按钮的sizer
        sizer = wx.BoxSizer(wx.VERTICAL)
        # 所有CheckListBox的sizer
        list_sizer = wx.BoxSizer(wx.HORIZONTAL)

        # region 新增文件部分的操作
        self.file_list = file_list = \
            wx.CheckListBox(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, [], 0)
        self.all_check = all_check = wx.CheckBox(self, wx.ID_ANY, label='All', style=wx.CHK_3STATE)
        # self.generate_layout(list_sizer, file_list, all_check)
        file_list_sizer = wx.BoxSizer(wx.VERTICAL)
        file_list_sizer.Add(all_check, 0, wx.SHAPED)
        file_list_sizer.Add(file_list, 1, wx.EXPAND)
        # 把所有的文件列表sizer放入统一的sizer管理
        list_sizer.Add(file_list_sizer, 1, wx.EXPAND)
        # endregion

        sizer.Add(list_sizer, 1, wx.EXPAND)
        self.SetSizer(sizer)

        # region connection
        self.Bind(wx.EVT_CHECKBOX, self.on_all_check_change, all_check)
        self.Bind(wx.EVT_CHECKLISTBOX, self.on_check_change, file_list)
        # endregion

    def on_check_change(self, event):
        check = self.all_check
        lst = self.file_list
        count = lst.GetCount()
        check_count = len(lst.GetCheckedStrings())
        check.Set3StateValue(wx.CHK_CHECKED if count == check_count
                             else wx.CHK_UNCHECKED if check_count == 0 else wx.CHK_UNDETERMINED)
        evt = WxChangeFileSelectionEvent(CHANGE_FILE_SELECTION_EVENT_TYPE, self.GetId())
        self.GetEventHandler().ProcessEvent(evt)

    # region 控制全选check的状态
    # check的全选
    def on_all_check_change(self, event):
        check = self.all_check
        file_list = self.file_list
        for i in range(0, file_list.GetCount()):
            file_list.Check(i, check.IsChecked())

        evt = WxChangeFileSelectionEvent(CHANGE_FILE_SELECTION_EVENT_TYPE, self.GetId())
        self.GetEventHandler().ProcessEvent(evt)

    # endregion

    def set_items(self, file_list):
        add_list = self.file_list
        add_list.AppendItems(file_list)


class VCSPanel(wx.Panel):
    def __init__(self, parent, id=wx.ID_ANY):
        wx.Panel.__init__(self, parent=parent, id=id)
        v_sizer = wx.BoxSizer(wx.VERTICAL)
        v_sizer.Fit(self)
        self.page_dic = {}
        self.notebook = notebook = wx.aui.AuiNotebook(self, style=wx.NB_TOP)
        self.SetSizer(v_sizer)

        # region 按钮操作
        # check in 按钮
        self.ci_btn = ci_btn = wx.Button(self, id=wx.ID_ANY, label=u'↑', pos=wx.DefaultPosition,
                                         size=wx.Size(24, 24), style=wx.BU_EXACTFIT)
        # 属性设定按钮
        self.property_btn = ppt_btn = wx.Button(self, id=wx.ID_ANY, label=u'P', pos=wx.DefaultPosition,
                                                size=wx.Size(24, 24), style=wx.BU_EXACTFIT)
        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
        button_sizer.Add(ci_btn, 0, wx.SHAPED)
        button_sizer.Add(ppt_btn, 0, wx.SHAPED)
        # endregion
        v_sizer.Add(notebook, 1, wx.EXPAND)
        v_sizer.Add(button_sizer, 0, wx.SHAPED)

        # connection
        self.Bind(wx.EVT_BUTTON, self.on_ci_click, ci_btn)

        # 按钮的状态控制
        self.ci_btn.Enable(False)
        self.property_btn.Enable(False)

    # 根据选定文件的数量设定check in 按钮和property按钮的状态
    def on_file_selection_changed(self, event):
        selected_strings = []
        notebook = self.notebook
        page_count = notebook.GetPageCount()
        for i in range(0, page_count):
            page = notebook.GetPage(i)
            selected_strings.extend(page.file_list.GetCheckedStrings())

        self.ci_btn.Enable(len(selected_strings) > 0)
        self.property_btn.Enable(len(selected_strings) > 0)

    def set_items(self, file_list_dic):
        page_dic = self.page_dic
        self.clear_pages()
        add_file_list = file_list_dic.get(ADD_LIST)
        self.add_list(add_file_list, page_dic, ADD_LIST)
        del_file_list = file_list_dic.get(DEL_LIST)
        self.add_list(del_file_list, page_dic, DEL_LIST)
        chg_file_list = file_list_dic.get(CHG_LIST)
        self.add_list(chg_file_list, page_dic, CHG_LIST)
        cfl_file_list = file_list_dic.get(CFL_LIST)
        self.add_list(cfl_file_list, page_dic, CFL_LIST)
        unv_file_list = file_list_dic.get(UNV_LIST)
        self.add_list(unv_file_list, page_dic, UNV_LIST)

    def get_file_list(self):
        pages = self.page_dic
        ret_dic = {}
        for (key, page) in pages.items():
            ret_dic[TITLE_KEY_DIC[key]] = page.file_list.GetCheckedStrings()
        return ret_dic

    def clear_pages(self):

        self.ci_btn.Enable(False)
        self.property_btn.Enable(False)

        notebook = self.notebook
        notebook.DeleteAllPages()
        page_dic = self.page_dic
        page_dic.clear()

    def add_list(self, add_file_list, page_dic, key):
        notebook = self.notebook
        if add_file_list and len(add_file_list) > 0:
            add_file_panel = FileListPanel(notebook, style=wx.NB_TOP)
            page_dic[key] = add_file_panel
            notebook.AddPage(add_file_panel, TITLE_KEY_DIC[key])
            add_file_panel.set_items(add_file_list)
            self.Bind(EVT_CHANGE_FILE_SELECTION, self.on_file_selection_changed, add_file_panel)

    def on_ci_click(self, event):
        # print self.get_file_list()
        dic = self.get_file_list()
        dialog = CommitDialog(self, size=(400, 640))
        dialog.set_file_list(dic)
        dialog.ShowModal()
        dialog.Destroy()
# endregion 文件面板主panel


# test code for debug
if __name__ == '__main__':

    app = wx.App()
    frame = wx.Frame(None, size=(400, 640))
    panel2 = CommitPanel(frame, id=wx.ID_ANY)
    # panel = VCSPanel(frame, id=wx.ID_ANY)
    # dic = {
    #     'add_list': ['01', '02'],
    #     'del_list': ['11', '12'],
    #     'chg_list': ['21', '22'],
    #     CFL_LIST: ['31', '32'],
    #     'unv_list': ['41', '42'],
    # }
    # panel.set_items(dic)

    dic2 = {
        '追加列表': ['1', '2'],
        '删除列表': ['3', '4'],
        '变更列表': ['5', '6'],
        '冲突列表': ['7', '8'],
        '版本外列表': ['9', '10']
    }
    panel2.set_file_list(dic2)

    app.SetTopWindow(frame)
    frame.Show()
    app.MainLoop()
